package service

import (
	"oa-system/internal/api/request"
	"oa-system/internal/model"
	"oa-system/internal/repository"
	"oa-system/pkg/errors"
	"oa-system/pkg/utils"
	"time"

	"golang.org/x/crypto/bcrypt"
)

type UserService interface {
	GetAllUsersWithRoles(page, pageSize int, departmentID *uint, email, name string, roleIDs []uint) ([]model.User, int64, error)
	CreateUser(req *request.CreateUserRequest) (*model.User, error)
	UpdateUser(id uint, req *request.UpdateUserRequest) (*model.User, error)
	DeleteUser(id uint) error
	Login(email, password string) (string, *model.User, error)
}

type userService struct {
	repo repository.UserRepository
}

func NewUserService(repo repository.UserRepository) UserService {
	return &userService{repo: repo}
}

func (s *userService) GetAllUsersWithRoles(page, pageSize int, departmentID *uint, email, name string, roleIDs []uint) ([]model.User, int64, error) {
	return s.repo.GetAllUsersWithRoles(page, pageSize, departmentID, email, name, roleIDs)
}

func (s *userService) CreateUser(req *request.CreateUserRequest) (*model.User, error) {
	// 检查邮箱是否已存在
	if exists, err := s.repo.ExistsByEmail(req.Email); err != nil {
		return nil, err
	} else if exists {
		return nil, errors.NewBadRequestError("邮箱已存在", nil)
	}

	// 检查手机号是否已存在
	if exists, err := s.repo.ExistsByPhone(req.Phone); err != nil {
		return nil, err
	} else if exists {
		return nil, errors.NewBadRequestError("手机号已存在", nil)
	}

	user := &model.User{
		Name:         req.Name,
		Email:        req.Email,
		Phone:        req.Phone,
		Password:     req.Phone,
		DepartmentID: req.DepartmentID,
	}

	return s.repo.CreateUser(user, req.RoleIDs)
}

func (s *userService) UpdateUser(id uint, req *request.UpdateUserRequest) (*model.User, error) {
	user, err := s.repo.GetUserByID(id)
	if err != nil {
		return nil, errors.NewNotFoundError("用户不存在", err)
	}

	// 只有当新邮箱与旧邮箱不同时，才检查邮箱是否被其他用户使用
	if req.Email != user.Email {
		if exists, err := s.repo.ExistsByEmailExcept(req.Email, id); err != nil {
			return nil, err
		} else if exists {
			return nil, errors.NewBadRequestError("邮箱已被其他用户使用", nil)
		}
		user.Email = req.Email
	}

	// 只有当新手机号与旧手机号不同时，才检查手机号是否被其他用户使用
	if req.Phone != user.Phone {
		if exists, err := s.repo.ExistsByPhoneExcept(req.Phone, id); err != nil {
			return nil, err
		} else if exists {
			return nil, errors.NewBadRequestError("手机号已被其他用户使用", nil)
		}
		user.Phone = req.Phone
	}

	user.Name = req.Name
	user.DepartmentID = req.DepartmentID
	if req.Password != "" {
		// 对新密码进行加密
		hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
		if err != nil {
			return nil, errors.NewInternalServerError("密码加密失败", err)
		}
		user.Password = string(hashedPassword)
	}

	return s.repo.UpdateUser(user, req.RoleIDs)
}

func (s *userService) DeleteUser(id uint) error {
	// 先检查用户是否存在
	if _, err := s.repo.GetUserByID(id); err != nil {
		return errors.NewNotFoundError("用户不存在", err)
	}

	return s.repo.DeleteUser(id)
}

func (s *userService) Login(email, password string) (string, *model.User, error) {
	user, err := s.repo.GetUserByEmail(email)
	if err != nil {
		return "", nil, errors.NewUnauthorizedError("邮箱或密码错误", err)
	}

	// 检查用户状态
	if !user.IsActive() {
		return "", nil, errors.NewUnauthorizedError("用户账号已被禁用", nil)
	}

	// 验证密码
	if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
		return "", nil, errors.NewUnauthorizedError("邮箱或密码错误", nil)
	}

	// 生成 JWT token
	token, err := utils.GenerateToken(user.ID, user.Email)
	if err != nil {
		return "", nil, errors.NewInternalServerError("生成token失败", err)
	}

	// 更新最后登录时间
	now := time.Now()
	user.LastLogin = &now
	user, err = s.repo.UpdateUser(user, nil)
	if err != nil {
		return "", nil, errors.NewInternalServerError("更新用户登录时间失败", err)
	}

	// 清除敏感信息
	user.Password = ""

	return token, user, nil
}
